/********************************************************************************
* @file    app_io_com.c
* @author  jianqiang.xue
* @version V1.1.0
* @date    2023-02-26
* @brief   IO功能--AT指令操作
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include "os_api.h"
#include "log.h"
#include "kv_sys.h"
#include "atcmd_slave.h"
#include "str_hex.h"
/* Private Includes ----------------------------------------------------------*/
#include "ls_gpio.h"
#include "ls_syscfg.h"

#include "ls_key.h"
#include "app_io.h"
/* ATCMD Function Prototypes -------------------------------------------------*/
#if ATCMD_EN
/* IO Func -------------------------------------------------------------------*/
static int atcmd_io_cfg_get_all(atcmd_pack_t *pack) {
    char buff[(LS_IO_NUM - 1) * 3 + 15] = {0};
    char temp[7] = {0};
    uint8_t len = 0;
    uint8_t s_len = 0;
    strncat(buff, "+IOCFGALL:", sizeof("+IOCFGALL:") - 1);
    s_len += sizeof("+IOCFGALL:") - 1;
    for (uint8_t i = 1; i < LS_IO_NUM; i++) {
        len = snprintf(temp, 5, "%u", g_io_cfg[i].type); // 1 为了跳过pin0，因为不存在
        strncat(buff, temp, len);
        s_len += len;
        if (i != LS_IO_NUM - 1) {
            strncat(buff, ",", 1);
            s_len += 1;
        }
    }
    strncat(buff, "\r\n", 2);
    s_len += 2;
    pack->reply((uint8_t*)buff, s_len);
    return 0;
}

// static int atcmd_io_use_cfg_get_all(atcmd_pack_t *pack) {
//     char buff[64*2+15] = {0};
//     uint64_t temp = g_cfg_record.support.val;
//     strcat(buff, "+USECFGALL=");
//     for (uint8_t i = 0; i < 64; i++) {
//         if (temp & 0x01) {
//             strncat(buff, "1", 1);
//         } else {
//             strncat(buff, "0", 1);
//         }
//         temp >>= 1;
//         if (i % 10 == 0)
//             strncat(buff, "\n", 1);
//     }
//     strcat((char*)buff, AT_OK);
//     pack->reply((uint8_t*)buff, strlen(buff));
//     return 0;
// }

static int atcmd_io_cfg_all(atcmd_pack_t *pack) {
    uint8_t argc[LS_IO_NUM - 1] = {0};
    char *arg; // 临时存放值
    uint8_t cnt = 0;
    char buff[30] = {0};
    uint8_t len = 0;
    arg = strtok((char*)(pack->data), ",");
    while (arg != NULL) {
        argc[cnt++] = (uint8_t)atoi(arg);
        arg = strtok(NULL, ",");
        if (cnt > LS_IO_NUM - 1)
            break;
    }
    pack->argc = cnt;
    if (pack->argc != LS_IO_NUM - 1) {
        len = snprintf(buff, 30, "+IOCFGALL:ARGCERR %u!=%u", pack->argc, LS_IO_NUM - 1);
        pack->reply((uint8_t *)buff, len);
        return -1;
    }
    // // 固定AT串口，不可改变，防止AT失效
    // argc[LS_IO_NUM-2] = IO_TYPE_UART0_RX;
    // argc[LS_IO_NUM-1] = IO_TYPE_UART0_TX;

    io_init_all((io_type_t *)argc, true); // 将引脚全部初始化,并记住配置
    if (g_io.flag.save_support == 1)
        g_io.flag.write_in = 1;
    len = snprintf(buff, 30, "+IOCFGALL:OK\r\n");
    pack->reply((uint8_t*)buff, len);
    return 0;
}

static int atcmd_io_cfg(atcmd_pack_t *pack) {
    uint32_t argc[2] = {0};
    char buff[35] = {0};
    uint8_t key_num = 0;
    uint8_t len = 0;
    pack->argc = sscanf((char*)(pack->data), "%u,%u", &argc[0], &argc[1]);
    if (pack->argc != 2) {
        len = snprintf(buff, 35, "+IOCFG:ARGCERR argc!=2\r\n");
        goto end;
    }
    if (argc[0] > LS_IO_NUM - 1) {
        len = snprintf(buff, 35, "+IOCFG:ARGCERR io_pin %u>%u\r\n", argc[0], LS_IO_NUM - 1);
        goto end;
    }
    if (argc[1] > IO_TYPE_MAX - 1) {
        len = snprintf(buff, 35, "+IOCFG:ARGCERR io_type %u>%u\r\n", argc[1], IO_TYPE_MAX - 1);
        goto end;
    }
    // if (g_io_cfg[argc[0]].type != argc[1]) {
    //     // if (g_io_cfg[argc[0]].type == IO_TYPE_KEY) {
    //     //     if (g_cfg_record.key_num != 0)
    //     //         g_cfg_record.key_num --;
    //     // }
    //     // io_cfg(argc[0], (io_type_t *)&argc[1], &g_cfg_record);
    //     // io_cfg_task_and_peripheral(&g_cfg_record); // 创建各类任务或自动开关外设
    //     // if (g_io.flag.save_support == 1)
    //     //     g_io.flag.write_in = 1;
    // }
    len = snprintf(buff, 35, "+IOCFG:OK\r\n");
    pack->reply((uint8_t*) buff, strlen((char*)buff));
    return 0;
end:
    pack->reply((uint8_t*) buff, strlen((char*)buff));
    return -1;
}

static int atcmd_set_io_all(atcmd_pack_t *pack) {
    uint8_t argc[LS_IO_NUM - 1] = {0};
    char *arg; // 临时存放值
    uint8_t cnt = 0;
    char buff[30] = {0};
    uint8_t len = 0;
    arg = strtok((char*)(pack->data), ",");
    while (arg != NULL) {
        argc[cnt++] = (uint8_t)atoi(arg);
        arg = strtok(NULL, ",");
        if (cnt > LS_IO_NUM - 1)
            break;
    }
    pack->argc = cnt;
    if (pack->argc != LS_IO_NUM - 1) {
        len = snprintf(buff, 30, "+IOALL:ARGCERR %u!=%u\r\n", pack->argc, LS_IO_NUM - 1);
        pack->reply((uint8_t *)buff, len);
        return -1;
    }
    for (uint8_t i = 1; i < LS_IO_NUM; i++) {
        if (g_io_cfg[i].type == IO_TYPE_OUT_PP)
            io_out(i, argc[i]);
    }
    len = snprintf(buff, 30, "+IOALL:OK\r\n");
    pack->reply((uint8_t*) buff, len);
    return 0;
}

static int atcmd_set_io(atcmd_pack_t *pack) {
    uint32_t argc[2] = {0};
    char buff[20] = {0};
    uint8_t len = 0;
    pack->argc = sscanf((char*)(pack->data), "%u,%u", &argc[0], &argc[1]);
    if (pack->argc != 2) return -1;
    if (argc[0] > LS_IO_NUM - 1) return -2;

    if (g_io_cfg[argc[0]].type == IO_TYPE_OUT_PP || g_io_cfg[argc[0]].type == IO_TYPE_OUT_OD) {
        io_out(argc[0], argc[1]);
        len = snprintf(buff, 20, "+IO=OK\r\n");
    } else if(g_io_cfg[argc[0]].type == IO_TYPE_SWO) {
        if (g_io.flag.swo_off)
            len = snprintf(buff, 20, "+IO=NO CFG SWO\r\n");
        else {
            io_out(argc[0], argc[1]);
            len = snprintf(buff, 20, "+IO=OK\r\n");
        }
    } else
        len = snprintf(buff, 20, "+IO=ERROR\r\n");

    pack->reply((uint8_t *)buff, len);
    return 0;
}

/**
 * @brief  得到IO电平状态
 */
static int atcmd_get_io(atcmd_pack_t *pack) {
    char buff[(LS_IO_NUM - 1) * 3 + 10] = {0};
    uint8_t s_len = 0;
    strncat(buff, "+IO:", sizeof("+IO:") - 1);
    s_len += sizeof("+IO:") - 1;
    for (uint8_t i = 1; i < LS_IO_NUM; i++) {
        char temp = get_io_ste(i) + '0';
        strncat(buff, &temp, 1);
        s_len += 1;
        if (i != LS_IO_NUM - 1) {
            s_len += 1;
            strncat(buff, ",", 1);
        }
    }
    strncat(buff, "\r\n", 2);
    s_len += 2;
    pack->reply((uint8_t*)buff, s_len);
    return 0;
}

/**
 * @brief  得到IO事件。io_event_t。中断、按键等。
 */
static int atcmd_get_event(atcmd_pack_t *pack) {
    char buff[(LS_IO_NUM - 1) * 3 + 10] = {0};
    char temp[4] = {0};
    uint8_t s_len = 0;
    uint8_t len = 0;
    strncat(buff, "+IOEVENT:", sizeof("+IOEVENT:") - 1);
    s_len += sizeof("+IOEVENT:") - 1;
    for (uint8_t i = 1; i < LS_IO_NUM; i++) {
        len = snprintf(temp, 4, "%u", g_io.func[i].io_event);
        strncat(buff, temp, len);
        s_len += len;
        if (i != LS_IO_NUM - 1) {
            s_len += 1;
            strncat(buff, ",", 1);
        }
    }
    strncat(buff, "\r\n", 2);
    s_len += 2;
    pack->reply((uint8_t*)buff, s_len);
    clean_signal_irq();
    return 0;
}

static int atcmd_set_io_save(atcmd_pack_t *pack) {
    uint32_t argc[1] = {0};
    char buff[15] = {0};
    uint8_t len = 0;
    pack->argc = sscanf((char*)(pack->data), "%u", &argc[0]);
    if (pack->argc != 1 || argc[0] > 1) return -1;
    g_io.flag.save_support = argc[0];
    len = snprintf(buff, 15, "+IOSAVE=OK\r\n");
    pack->reply((uint8_t*)buff, len);
    return 0;
}

static int atcmd_get_io_info(atcmd_pack_t *pack) {
    char buff[60] = {0};
    uint8_t len = 0;
    len = snprintf(buff, 60, "+IOINFO:%s,%s,%u,%u\r\n",
                   CHIP_IC, IO_VERSION, g_io.flag.save_support, LS_IO_NUM - 1);
    pack->reply((uint8_t*)buff, len);
    return 0;
}

//ATCMD_INIT("AT+IOCFGALL=", atcmd_io_cfg_all);
ATCMD_INIT("AT+IOCFGALL?", atcmd_io_cfg_get_all);
//ATCMD_INIT("AT+IOCFG=", atcmd_io_cfg);
ATCMD_INIT("AT+IOALL=", atcmd_set_io_all);
ATCMD_INIT("AT+IO=", atcmd_set_io);
ATCMD_INIT("AT+IO?", atcmd_get_io);
ATCMD_INIT("AT+IOEVENT?", atcmd_get_event);

ATCMD_INIT("AT+IOSAVE=", atcmd_set_io_save);
ATCMD_INIT("AT+IOINFO?", atcmd_get_io_info);
/* IO Task Func ---------------------------------------------------------------*/

#endif
